/**
动态代理有以下特点:
1.代理对象,不需要实现接口
2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
3.动态代理也叫做:JDK代理,接口代理

缺点:
	代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
	
	目标对象没有实现接口,用Cglib代理

**/
import java.lang.reflect.*;

class Untitled {
	public static void main(String[] args) {
		// 目标对象
		IUserDao target = new UserDao();
		// 【原始的类型 class cn.itcast.b_dynamic.UserDao】
		System.out.println(target.getClass());

		// 给目标对象，创建代理对象
		IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
		// class $Proxy0   内存中动态生成的代理对象
		System.out.println(proxy.getClass());

		// 执行方法   【代理对象】
		proxy.save();
	}
}

/**
 * 接口
 */
interface IUserDao {

	void save();
}

/**
 * 接口实现
 * 目标对象
 */
class UserDao implements IUserDao {
	public void save() {
		System.out.println("----已经保存数据!----");
	}
}

/**
 * 创建动态代理对象
 * 动态代理不需要实现接口,但是需要指定接口类型
 */
class ProxyFactory{

	//维护一个目标对象
	private Object target;
	public ProxyFactory(Object target){
		this.target=target;
	}

   //给目标对象生成代理对象
	public Object getProxyInstance(){
		return Proxy.newProxyInstance(
				target.getClass().getClassLoader(),
				target.getClass().getInterfaces(),
				new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("开始事务2");
						//执行目标对象方法
						Object returnValue = method.invoke(target, args);
						System.out.println("提交事务2");
						return returnValue;
					}
				}
		);
	}

}